package com.echartsdata.config;
import com.echartsdata.Entity.User;
import com.echartsdata.Entityimp.Userimp;
import com.echartsdata.jwt.JwtAuthenticationEntryPoint;
import com.echartsdata.jwt.JwtRequestFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.annotation.Resource;

/*****
 *   凉笙℡墨染
 *   2025-7-10
 *   访问授权配置管理
 *   说明：此类是Spring Security的核心配置类，负责配置认证机制、授权规则、JWT集成及安全过滤链
 */
@Configuration // 标识为配置类，Spring会自动扫描并加载
@EnableWebSecurity // 启用Spring Security的Web安全支持
public class SecurityConfig extends WebSecurityConfigurerAdapter { // 继承适配器，简化安全配置

    @Resource
    private Userimp userimp; // 用户服务实现类，用于从数据库获取用户信息（依赖注入）

    @Autowired
    private JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint; // 未授权访问时的处理入口（401响应）

    @Autowired
    private JwtRequestFilter jwtRequestFilter; // JWT请求过滤器，用于验证请求中的令牌

    /**
     * 配置密码编码器
     * 使用BCrypt算法对密码进行加密存储，防止明文泄露
     * BCrypt是不可逆加密，每次加密结果不同，但可验证一致性
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置认证管理器（AuthenticationManager）
     * 指定用户详情服务（UserDetailsService）和密码编码器，用于处理用户认证逻辑
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 设置用户详情服务和密码编码器，使认证管理器知道如何获取用户信息及验证密码
        auth.userDetailsService(userDetailsServiceBean()).passwordEncoder(passwordEncoder());
    }

    /**
     * 定义用户详情服务（UserDetailsService）
     * 实现Spring Security的用户详情接口，用于从数据库加载用户信息并转换为框架可识别的UserDetails对象
     * 是认证流程的核心，负责提供用户信息（用户名、密码、权限等）
     */
    @Bean
    @Override
    public UserDetailsService userDetailsServiceBean() {
        return new UserDetailsService() {
            @Override
            public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
                // 1. 从数据库获取用户信息（通过自定义的Userimp服务）
                User user = userimp.get_user(username);
                System.out.print("从数据库查询到的用户信息: " + user); // 调试用，生产环境可删除

                // 2. 检查用户是否存在，不存在则抛出异常
                if (user == null) {
                    throw new UsernameNotFoundException("不存在当前用户: " + username);
                }

                // 3. 将数据库用户对象转换为Spring Security的UserDetails对象
                // 包含用户名、加密后的密码、角色权限（这里默认赋予USER角色）
                return org.springframework.security.core.userdetails.User.builder()
                        .username(user.getUsername()) // 设置用户名
                        .password(user.getPassword()) // 数据库中存储的必须是加密后的密码
                        .roles("USER") // 赋予用户基础角色（可根据实际业务扩展）
                        .build();
            }
        };
    }

    /**
     * 暴露认证管理器（AuthenticationManager）为Bean
     * 供外部组件（如登录接口）调用，处理用户认证请求（如用户名密码登录）
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 配置HTTP安全策略
     * 定义哪些请求需要认证、哪些可以匿名访问，配置异常处理、会话管理及过滤器链
     * 是Spring Security的核心安全配置方法
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // 1. 禁用CSRF保护（适用于无状态API，JWT本身已提供安全机制）
                .csrf().disable()

                // 2. 配置授权规则
                .authorizeRequests()
                // 放行无需认证的路径（如登录、注册、静态资源）
                .antMatchers(
                        "/index",         // 首页大屏（公开访问）
                        "/authenticate",  // 登录接口（获取JWT令牌）
                        "/register",      // 注册接口（公开访问）
                        "/css/**",        // CSS静态资源
                        "/js/**",         // JS静态资源
                        "/images/**",     // 图片资源
                        "/static/**",     // 静态资源目录
                        "/**/*.css",      // 所有CSS文件
                        "/**/*.js",       // 所有JS文件
                        "/**/*.png",      // 所有PNG图片
                        "/**/*.ico"       // 图标文件
                ).permitAll() // 允许匿名访问上述路径
                // 其他所有请求必须经过认证
                .anyRequest().authenticated()

                // 3. 配置异常处理：未授权访问时由jwtAuthenticationEntryPoint处理
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(jwtAuthenticationEntryPoint)

                // 4. 配置会话管理：使用无状态会话（JWT是无状态的，不依赖Session）
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS); // 不创建Session

        // 5. 添加JWT过滤器到安全链中
        // 将JwtRequestFilter放在UsernamePasswordAuthenticationFilter之前，优先验证JWT令牌
        httpSecurity.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
    }
}